package com.ttn.business.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.ttn.business.mapper.OrderMapper;
import com.ttn.business.openfeign.StudentRecordFeignService;
import com.ttn.business.service.OrderService;
import com.ttn.business.service.ProductService;
import com.ttn.common.core.entity.Result;
import com.ttn.common.core.entity.business.Order;
import com.ttn.common.core.entity.business.Product;
import com.ttn.common.core.entity.business.query.OrderPageQuery;
import com.ttn.common.core.entity.business.vo.OrderDetailsVO;
import com.ttn.common.core.entity.business.vo.QueryOrderStatisticsVO;
import com.ttn.common.core.entity.business.vo.SaveOrderVO;
import com.ttn.common.core.entity.studentrecord.StudentRecord;
import com.ttn.common.core.util.OrderNumGeneratorUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    @Resource
    private OrderMapper orderMapper;
    @Resource
    private ProductService productService;
    @Resource
    private StudentRecordFeignService studentRecordFeignService;

    @Resource
    private WxPayService wxPayService;


    @Override
    public Result saveOrder(Order order) {
        SaveOrderVO saveOrderVO = new SaveOrderVO();
        //判断购买的产品是否存在
        Product product = productService.getById(order.getProductId());
        if (Objects.isNull(product)) {
            Result.fail("购买的产品不存在,请确认后购买");
        }
        order.setProductId(product.getId());
        order.setProductName(product.getProductName());
        order.setProductType(product.getProductType());
        order.setProductPrice(product.getProductPrice());
        order.setOutTradeNo(IdUtil.objectId());
        order.setServicePeriod(product.getServicePeriod());
        order.setAmountsPayable(product.getProductPrice());
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderLambdaQueryWrapper.ge(Order::getCreateTime, DateUtil.beginOfDay(DateUtil.date()));
        orderLambdaQueryWrapper.le(Order::getCreateTime, DateUtil.endOfDay(DateUtil.date()));
        order.setOrderNumber(OrderNumGeneratorUtil.generatorOrderNum(Math.toIntExact(this.count(orderLambdaQueryWrapper) + 1)));
        //手动创建订单，直接保存
        if (Objects.nonNull(order.getPaymentMethod()) && order.getPaymentMethod().equals(3)) {
            order.setPaymentTime(DateTime.now());
            order.setOrderStatus(1);
            order.setAmountsPayable(product.getProductPrice() - order.getDiscountedPrice());
            //更新用户的服务器
            if (Objects.nonNull(order)) {
                log.info("开始更新服务期时间", order);
                studentRecordFeignService.modifyStudentRecordDeadLine(order);
            }
        }
        this.save(order);
        saveOrderVO.setId(order.getId()).setOrderNumber(order.getOrderNumber());
        return Result.success(saveOrderVO);
    }


    @Override
    public Result saveOrderByStudent(Order order, HttpServletRequest request) {
        order.setPaymentMethod(1);
        Result<SaveOrderVO> saveOrderVOResult = saveOrder(order);
        WxPayMpOrderResult wxPayMpOrderResult = null;
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = null;
        if (Objects.nonNull(saveOrderVOResult)) {
            Order queryOrder = this.getById(saveOrderVOResult.getData().getId());
            if (Objects.nonNull(queryOrder)) {
                Result<StudentRecord> studentRecordResult =
                        studentRecordFeignService.serviceQueryStudentRecordById(order.getStudentId());
                if (Objects.nonNull(studentRecordResult.getData())) {
                    try {
                        wxPayUnifiedOrderRequest = WxPayUnifiedOrderRequest.newBuilder()
                                //调起支付的人的 openId
                                .openid(studentRecordResult.getData().getOpenId())
                                //交易类型
                                .tradeType("JSAPI")
                                //订单编号
                                .outTradeNo(queryOrder.getOutTradeNo())
                                //订单金额
                                .totalFee(queryOrder.getProductPrice())
                                //商品描述
                                .body(queryOrder.getProductName())

                                //获取本地IP
                                .spbillCreateIp(ServletUtil.getClientIP(request, null))
                                //回调的 URL 地址
                                .notifyUrl("http://ttn2022.ttiannian.com/dev-api/ttn-business/order/weChatPayNotify").build();

                        wxPayMpOrderResult = wxPayService.createOrder(wxPayUnifiedOrderRequest);
                        log.info("微信调用返回wxPayUnifiedOrderResult{}:", wxPayMpOrderResult);
                    } catch (WxPayException e) {
                        log.info("微信调用错误，参数为wxPayUnifiedOrderRequest:{}，错误信息为WxPayException：{}",
                                wxPayUnifiedOrderRequest, e);
                        throw new RuntimeException(e);
                    }
                }

            }
        }

        return Result.success(wxPayMpOrderResult);
    }

    @Override
    public Result queryOrderPage(OrderPageQuery orderPageQuery) {
        IPage<Order> orderIPage = new Page<>(orderPageQuery.getPageNum(), orderPageQuery.getPageSize());

        return Result.success(orderMapper.queryOrderPage(orderIPage, orderPageQuery));
    }

    @Override
    public Result queryOrderDetailsByOrderNumber(String orderNumber) {
        OrderDetailsVO orderDetailsVO = new OrderDetailsVO();
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderLambdaQueryWrapper.eq(Order::getOrderNumber, orderNumber);
        Order order = this.getOne(orderLambdaQueryWrapper);
        if (Objects.nonNull(order)) {
            orderDetailsVO.setOrder(order);
            Result<StudentRecord> studentRecordFeignResult = studentRecordFeignService.serviceQueryStudentRecordById(order.getStudentId());
            if (studentRecordFeignResult.isSuccess()) {
                orderDetailsVO.setStudentRecord(studentRecordFeignResult.getData());
            }
            orderDetailsVO.setProduct(productService.getById(order.getProductId()));

        }
        return Result.success(orderDetailsVO);
    }

    @Override
    public Result paymentOrderSuccessful(String orderNumber) {
        LambdaUpdateWrapper<Order> orderLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        orderLambdaUpdateWrapper.eq(Order::getOutTradeNo, orderNumber);
        orderLambdaUpdateWrapper.set(Order::getOrderStatus, 1);
        orderLambdaUpdateWrapper.set(Order::getPaymentTime, DateTime.now());
        //更新订单状态
        this.update(orderLambdaUpdateWrapper);
        //更新用户的服务期
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderLambdaQueryWrapper.eq(Order::getOutTradeNo, orderNumber);
        Order order = this.getOne(orderLambdaQueryWrapper);
        if (Objects.nonNull(order)) {
            log.info("开始更新服务期时间", order);
            studentRecordFeignService.modifyStudentRecordDeadLine(order);
        }

        //修改用户有效时间
        return null;
    }

    @Override
    public Result queryOrderStatistics() {
        Map<String, QueryOrderStatisticsVO> queryOrderStatisticsVOMap = new HashMap<>();
        return Result.success(queryOrderStatisticsVOMap);
    }
}
